# 239. 滑动窗口最大值
# 给你一个整数数组 nums，有一个大小为k的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k个数字。滑动窗口每次只向右移动一位。
# 返回 滑动窗口中的最大值 。
#
# 示例 1：
# 输入：nums = [1,3,-1,-3,5,3,6,7], k = 3
# 输出：[3,3,5,5,6,7]
# 解释：
# 滑动窗口的位置                最大值
# ---------------               -----
# [1  3  -1] -3  5  3  6  7       3
#  1 [3  -1  -3] 5  3  6  7       3
#  1  3 [-1  -3  5] 3  6  7       5
#  1  3  -1 [-3  5  3] 6  7       5
#  1  3  -1  -3 [5  3  6] 7       6
#  1  3  -1  -3  5 [3  6  7]      7
#
# 示例 2：
# 输入：nums = [1], k = 1
# 输出：[1]


from collections import deque
class Myqueue:
    def __init__(self):
        self.queue = deque()

    # 每次弹出的时候，比较当前要弹出的数值是否等于队列出口元素的数值，如果相等则弹出。
    # 同时pop之前判断队列当前是否为空。
    def pop(self, val):
        if self.queue and val ==self.queue[0]:
            self.queue.popleft()

    # 如果push的数值大于入口元素的数值，那么就将队列后端的数值弹出，直到push的数值小于等于队列入口元素的数值为止。
    # 这样就保持了队列里的数值是单调从大到小的了。
    def push(self, val):
        while self.queue and val > self.queue[-1]:
            self.queue.pop()
        self.queue.append(val)

    def get_max_val(self):
        return self.queue[0]


class Solution:
    def maxSlidingWindow(self, nums:[int], k: int) ->[int]:
        my = Myqueue()
        long = len(nums)
        res = []
        for i in range(k):
            my.push(nums[i])
        res.append(my.get_max_val())
        for i in range(k,long):
            my.pop(nums[i-k]) # #滑动窗口移除最前面元素
            my.push(nums[i])
            res.append(my.get_max_val())
        return res

if __name__ == '__main__':
    nums = [1,3,-1,-3,5,3,6,7]
    k = 3
    tmp = Solution()
    res = tmp.maxSlidingWindow(nums,k)
    print(res)
    # 看了两三次，基本弄根本明白了
